package com.lzh.chatnote.common.exception;

import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
import cn.dev33.satoken.util.SaResult;
import com.lzh.chatnote.common.domain.response.ApiResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * 全局异常捕获处理器
 */

@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    /**
     * validation参数校验异常
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public ApiResult methodArgumentNotValidExceptionExceptionHandler(MethodArgumentNotValidException e) {
        StringBuilder errorMsg = new StringBuilder();
        e.getBindingResult().getFieldErrors()
                .forEach(x -> errorMsg
                        .append(x.getField())
                        .append(x.getDefaultMessage())
                        .append(","));
        String message = errorMsg.toString();
        log.info("validation parameters error！The reason is:{}", message);
        return ApiResult.fail(CommonErrorEnum.PARAM_VALID.getErrorCode(), message.substring(0, message.length() - 1));
    }

    /**
     * validation参数校验异常 手动抛出异常 时候会被捕获
     *    User user = new User();
     *    user.setEmail("invalid-email");
     *    ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
     *    Validator validator = factory.getValidator();
     *    Set<ConstraintViolation<User>> violations = validator.validate(user);
     *    if (!violations.isEmpty()) {
     *        throw new BindException(violations);  // 手动抛出 BindException
     *    }
     */
    @ExceptionHandler(value = BindException.class)
    public ApiResult bindException(BindException e) {
        StringBuilder errorMsg = new StringBuilder();
        e.getBindingResult().getFieldErrors().forEach(x -> errorMsg.append(x.getField()).append(x.getDefaultMessage()).append(","));
        String message = errorMsg.toString();
        log.info("validation parameters error！The reason is:{}", message);
        return ApiResult.fail(CommonErrorEnum.PARAM_VALID.getErrorCode(), message.substring(0, message.length() - 1));
    }

    /**
     * 处理空指针的异常
     */
    @ExceptionHandler(value = NullPointerException.class)
    public ApiResult exceptionHandler(NullPointerException e) {
        log.error("null point exception！The reason is: ", e);
        return ApiResult.fail(CommonErrorEnum.SYSTEM_ERROR);
    }

    /**
     * 未知异常,保底异常
     */
    @ExceptionHandler(value = Exception.class)
    public ApiResult systemExceptionHandler(Exception e) {
        log.error("system exception！The reason is：{}", e.getMessage(), e);
        return ApiResult.fail(CommonErrorEnum.SYSTEM_ERROR);
    }

    /**
     * 自定义校验异常（如参数校验等）
     */
    @ExceptionHandler(value = BusinessException.class)
    public ApiResult businessExceptionHandler(BusinessException e) {
        log.info("business exception！The reason is：{}", e.getMessage(), e);
        return ApiResult.fail(e.getErrorCode(), e.getMessage());
    }

    /**
     * http请求方式不支持
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public ApiResult<Void> handleException(HttpRequestMethodNotSupportedException e) {
        log.error(e.getMessage(), e);
        return ApiResult.fail(-1, String.format("不支持'%s'请求", e.getMethod()));
    }

    // 全局异常拦截
    @ExceptionHandler(NotPermissionException.class)
    public ApiResult notPermissionException(NotPermissionException e) {
        log.error(e.getMessage(), e);
        return ApiResult.fail(CommonErrorEnum.USER_NO_PERMISSION);
    }

    @ExceptionHandler( NotRoleException.class)
    public ApiResult notRoleExceptionHandler(NotRoleException e) {
        log.error(e.getMessage(), e);
        return ApiResult.fail(CommonErrorEnum.USER_NO_ROLE);
    }


    @ExceptionHandler(value = NotLoginException.class)
    public ApiResult notLoginExceptionHandler(NotLoginException e) {
        log.error(e.getMessage(), e);
        return ApiResult.fail(CommonErrorEnum.USER_TOKEN_INVALIDATE);
    }

    /**
     * 限流异常
     */
//    @ExceptionHandler(value = FrequencyControlException.class)
//    public ApiResult frequencyControlExceptionHandler(FrequencyControlException e) {
//        log.info("frequencyControl exception！The reason is：{}", e.getMessage(), e);
//        return ApiResult.fail(e.getErrorCode(), e.getMessage());
//    }
}
